package br.com.conciliador.download.apresentacao;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import br.com.conciliador.cadastro.negocio.BandeiraNgc;
import br.com.conciliador.cadastro.negocio.EstLojaNgc;
import br.com.conciliador.cadastro.negocio.FatoNgc;
import br.com.conciliador.cadastro.negocio.ProdutoNgc;
import br.com.conciliador.cadastro.vo.BandeiraVo;
import br.com.conciliador.cadastro.vo.EstLojaVo;
import br.com.conciliador.cadastro.vo.FatoVo;
import br.com.conciliador.cadastro.vo.LojaVo;
import br.com.conciliador.cadastro.vo.ProdutoVo;
import br.com.conciliador.cadastro.vo.StatusVo;
import br.com.conciliador.cadastro.vo.filtro.FiltroFatoVo;
import br.com.conciliador.download.negocio.GerarArquivoBaixaNgc;
import br.com.conciliador.download.negocio.GerarArquivoNgc;
import br.com.conciliador.download.vo.GerarArquivoBaixaVo;
import br.com.conciliador.download.vo.GerarArquivoVo;
import br.com.conciliador.download.vo.filtro.FiltroGerarArquivoBaixaVo;
import br.com.conciliador.download.vo.filtro.FiltroGerarArquivoVo;
import br.com.conciliador.seguranca.vo.ExtensaoUsuarioVo;
import br.com.conciliador.seguranca.vo.UsuarioVo;
import br.com.conciliador.util.jsf.AbstractBean;
import br.com.conciliador.util.jsf.JSFUtil;
import br.com.r2.exception.R2Exception;
import br.com.r2.util.tipodado.Data;
import br.com.r2.util.tipodado.Flag;
import br.com.r2.util.tipodado.Inteiro;
import br.com.r2.util.tipodado.InteiroLongo;
import br.com.r2.util.tipodado.Moeda;
import br.com.r2.util.tipodado.Texto;
import br.com.r2.util.tipodado.YesNo;

public class GerarArquivoBean extends AbstractBean<GerarArquivoVo, GerarArquivoNgc>
{

   private List<EstLojaVo> listaEstLojas;

   private List<BandeiraVo> listaBandeiras;

   private List<ProdutoVo> listaProdutos;
   
   private Inteiro quantidadeRegistros;
   
   private Moeda valorRegistros;
   
   private Moeda valorRegistrosLiquido;
   
   private boolean gerarArquivo;
   
   private boolean exibirListaLojas;
   
   JSFUtil util = new JSFUtil();
   
   public GerarArquivoBean()
   {
      super(GerarArquivoNgc.getInstancia());
      this.ACTION_SEARCH = "gerarArquivo";
      this.pageTitle = "titulo_gerar_arquivo";
   }

   @Override
   public String getFullTitle()
   {
      return util.getBundle().getString("titulo_gerar_arquivo");
   }
   @Override
   public String preparaPesquisar()
   {

      String retorno = super.preparaPesquisar();
      this.getSearchObject().setFiltro(new FiltroGerarArquivoVo());
      this.getSearchObject().setSituacao(new InteiroLongo(0));

      if (this.getSearchObject().getFiltro() == null)
      {
         this.getSearchObject().setFiltro(new FiltroGerarArquivoVo());
      }
      try
      {
         this.getSearchObject().getFiltro().setUsuarioVo(util.getUsuarioLogado());
      }
      catch (R2Exception e)
      {
         e.printStackTrace();
      }
      
      Data filtroData = new Data(new Date());
      this.getSearchObject().getFiltro().setDataVendaFinal(filtroData);
      filtroData = new Data(new Date());
      filtroData.add(GregorianCalendar.DAY_OF_WEEK_IN_MONTH, -1);
      this.getSearchObject().getFiltro().setDataVendaInicial(filtroData);

      return retorno;
   }

   @Override
   protected void setListaPesquisa() throws R2Exception
   {
      setarListaEstLojas();
      setarListaBandeiras();
   }

   private void setarListaEstLojas() throws R2Exception
   {
	      UsuarioVo usuarioVo = util.getUsuarioVo();
	      this.setExibirListaLojas(true);

	      if (usuarioVo == null)
	      {
	         throw new R2Exception("usuario.logado.nao.sessao");
	      }

	      if (usuarioVo.getEstEmpresaVo() == null || usuarioVo.getEstEmpresaVo().getCodigo() == null || !usuarioVo.getEstEmpresaVo().getCodigo().isPreenchido())
	      {
	         throw new R2Exception("usuario.logado.sem.empresa");
	      }

	      this.listaEstLojas = new ArrayList<EstLojaVo>();
	      
	      if (usuarioVo.getListaExtensaoUsuarioVo() == null || usuarioVo.getListaExtensaoUsuarioVo().size() == 0)
	      {
	         EstLojaVo estLojaVo = new EstLojaVo();
	         estLojaVo.setEstEmpresaVo(usuarioVo.getEstEmpresaVo());
	         estLojaVo.setSituacao(new Flag(YesNo.YES));
	         
	         List<EstLojaVo> lista = EstLojaNgc.getInstancia().pesquisar(estLojaVo, EstLojaNgc.JOIN_EST_EMPRESA);

	         EstLojaVo vazio = new EstLojaVo();
	         vazio.setDescricao(new Texto("TODAS"));

	         this.listaEstLojas.add(vazio);
	         this.listaEstLojas.addAll(lista);
	      }
	      else if (usuarioVo.getListaExtensaoUsuarioVo().size() > 1)
	      {
	         EstLojaVo vazio = new EstLojaVo();
	         vazio.setDescricao(new Texto("TODAS"));
	         this.listaEstLojas.add(vazio);
	         
	         List<EstLojaVo> lista = new ArrayList<EstLojaVo>();
	         Iterator<ExtensaoUsuarioVo> iterator = usuarioVo.getListaExtensaoUsuarioVo().iterator();
	         while (iterator.hasNext())
	         {
	            ExtensaoUsuarioVo element = (ExtensaoUsuarioVo) iterator.next();
	            lista.add(element.getEstLojaVo());
	         }
	         
	         Collections.sort(lista, new Comparator()
	         {
	            public int compare(Object o1, Object o2)
	            {
	               String c1 = ((EstLojaVo) o1).getDescricao().getValor();
	               String c2 = ((EstLojaVo) o2).getDescricao().getValor();
	               return c1.compareTo(c2);
	            }
	         }
	         );
	         
	         this.listaEstLojas.addAll(lista);
	      }
	      else
	      {
	         List<ExtensaoUsuarioVo> lista = new ArrayList<ExtensaoUsuarioVo>(usuarioVo.getListaExtensaoUsuarioVo());
	         ExtensaoUsuarioVo extensaoUsuarioVo = (ExtensaoUsuarioVo) lista.get(0);
	         if (this.getSearchObject().getFiltro() == null)
	         {
	            this.getSearchObject().setFiltro(new FiltroGerarArquivoVo());
	         }
	         this.getSearchObject().getFiltro().setEstLoja(extensaoUsuarioVo.getEstLojaVo().getCodigo());
	         this.getSearchObject().getFiltro().setNomeEstLoja(extensaoUsuarioVo.getEstLojaVo().getDescricao());
	         this.setExibirListaLojas(false);
	      }
   }

   private void setarListaBandeiras() throws R2Exception
   {
      this.listaBandeiras = new ArrayList<BandeiraVo>();
      BandeiraVo bandeiraVo = new BandeiraVo();
      List<BandeiraVo> lista = BandeiraNgc.getInstancia().pesquisar(bandeiraVo,0);

      BandeiraVo vazio = new BandeiraVo();
      vazio.setDescricao(new Texto("TODAS"));

      this.listaBandeiras.add(vazio);
      this.listaBandeiras.addAll(lista);
   }

   public void setarListaProdutos(ActionEvent event) throws R2Exception
   {
      if (this.getSearchObject().getBandeira() != null
          && this.getSearchObject().getBandeira().isPreenchido())
      {
         ProdutoVo produtoVo = new ProdutoVo();
         produtoVo.setFlagAtivo(new Flag(YesNo.YES));
         BandeiraVo bandeiraVo = new BandeiraVo();
         bandeiraVo.setCodigo(this.getSearchObject().getBandeira());
         produtoVo.setBandeiraVo(bandeiraVo);
         int join = ProdutoNgc.JOIN_BANDEIRA;
         List<ProdutoVo> lista = ProdutoNgc.getInstancia().pesquisar(produtoVo, join);
         
         produtoVo = new ProdutoVo();
         produtoVo.setDescricao(new Texto("TODOS"));
         this.setListaProdutos(new ArrayList<ProdutoVo>());
         this.getListaProdutos().add(produtoVo);
         if (lista != null)
         {
            this.getListaProdutos().addAll(lista);
         }
      }
   }
   
   public void simular(ActionEvent event)
   {
      try
      {
         validarSimular();
    
         List<InteiroLongo> listaStatus = new ArrayList<InteiroLongo>();
         InteiroLongo situacao = new InteiroLongo(2); // CONFIRMADA
         listaStatus.add(situacao);
         this.getSearchObject().getFiltro().setListaStatus(listaStatus);
         //situacao = this.getSearchObject().getSituacao();
         //this.getSearchObject().setSituacao(null);
            
         List<GerarArquivoVo> resultado = GerarArquivoNgc.getInstancia().simularGeracaoArquivoBaixa(this.getSearchObject(), 0);
         int qtde = 0;
         double valor = 0;
         double valorLiquido = 0;

         if (resultado != null && resultado.size() > 0)
         {
            setGerarArquivo(true);
            // SETANDO OS TOTAIS
            Iterator<GerarArquivoVo> iterator = resultado.iterator();
            while (iterator.hasNext())
            {
               GerarArquivoVo element = (GerarArquivoVo) iterator.next();
               
               qtde += element.getFiltro().getQuantidade().getValor();
               valor += element.getValorBruto().getValor();
               valorLiquido += element.getValorPago().getValor();
            }
         }
         else
         {
            setGerarArquivo(false);
         }
         this.setSearchResult(resultado);
         this.getSearchObject().setSituacao(situacao);
         quantidadeRegistros = new Inteiro(qtde);
         valorRegistros = new Moeda(valor);
         valorRegistrosLiquido = new Moeda(valorLiquido);
         setCurrentState(STATE_SEARCH);
      }
      catch (R2Exception e)
      {
         FacesMessage message = new FacesMessage(e.getMensagem());
         message.setSeverity(FacesMessage.SEVERITY_ERROR);
         FacesContext.getCurrentInstance().addMessage("", message);
      }
   }
   
   public void gerar(ActionEvent event)
   {
      try
      {
         validarSimular();
    
         List<InteiroLongo> listaStatus = new ArrayList<InteiroLongo>();
         InteiroLongo situacao = new InteiroLongo(0);
         if (this.getSearchObject().getSituacao() != null && this.getSearchObject().getSituacao().getValor() == 0)
         {
            
            situacao = new InteiroLongo(3); // NORMAL (LIQUIDADO)
            listaStatus.add(situacao);

            situacao = new InteiroLongo(5); // ANTECIPADA
            listaStatus.add(situacao);
            
            this.getSearchObject().getFiltro().setListaStatus(listaStatus);
            situacao = this.getSearchObject().getSituacao();
            this.getSearchObject().setSituacao(null);
         }
         else
         {
            listaStatus.add(this.getSearchObject().getSituacao());
            
            this.getSearchObject().getFiltro().setListaStatus(listaStatus);
            situacao = this.getSearchObject().getSituacao();
            this.getSearchObject().setSituacao(null);
            
         }
         this.getSearchObject().getFiltro().setUsuarioVo(util.getUsuarioLogado());
         
         GerarArquivoNgc.getInstancia().gerar(this.getSearchObject(), 0);
         
         
         this.getSearchObject().setSituacao(situacao);
         this.setSearchResult(null);
         setCurrentState(STATE_SEARCH);
         FacesContext.getCurrentInstance().addMessage(null,new FacesMessage(FacesMessage.SEVERITY_INFO,
                                                                            util.getBundle().getString("arquivo.gerado.sucesso"), null));
      }
      catch (R2Exception e)
      {
         FacesMessage message = new FacesMessage(e.getMensagem());
         message.setSeverity(FacesMessage.SEVERITY_ERROR);
         FacesContext.getCurrentInstance().addMessage("", message);
      }
   }

   private void validarSimular() throws R2Exception
   {
      GerarArquivoVo filtroVo = this.getSearchObject();

      if (filtroVo == null)
      {
         throw new R2Exception("campo_periodo_obrigatorio");
      }

      if (filtroVo.getFiltro().getDataVendaInicial() == null || !filtroVo.getFiltro().getDataVendaInicial().isPreenchido())
      {
         throw new R2Exception("campo_periodo_obrigatorio");
      }

      if (filtroVo.getFiltro().getDataVendaFinal() == null || !filtroVo.getFiltro().getDataVendaFinal().isPreenchido())
      {
         throw new R2Exception("campo_periodo_obrigatorio");
      }
      
      if (filtroVo.getFiltro().getDataVendaFinal().quantoPassou(filtroVo.getFiltro().getDataVendaInicial(), Data.DIAS) > 30)
      {
         throw new R2Exception("campo_periodo_fora_limite_30");
      }
      
   }

   public List<EstLojaVo> getListaEstLojas()
   {
      return listaEstLojas;
   }

   public void setListaEstLojas(List<EstLojaVo> listaEstLojas)
   {
      this.listaEstLojas = listaEstLojas;
   }

   public List<BandeiraVo> getListaBandeiras()
   {
      return listaBandeiras;
   }

   public void setListaBandeiras(List<BandeiraVo> listaBandeiras)
   {
      this.listaBandeiras = listaBandeiras;
   }

   public List<ProdutoVo> getListaProdutos()
   {
      return listaProdutos;
   }

   public void setListaProdutos(List<ProdutoVo> listaProdutos)
   {
      this.listaProdutos = listaProdutos;
   }
   
   public Inteiro getQuantidadeRegistros()
   {
      return quantidadeRegistros;
   }

   public void setQuantidadeRegistros(Inteiro quantidadeRegistros)
   {
      this.quantidadeRegistros = quantidadeRegistros;
   }

   public Moeda getValorRegistros()
   {
      return valorRegistros;
   }

   public void setValorRegistros(Moeda valorRegistros)
   {
      this.valorRegistros = valorRegistros;
   }

   public Moeda getValorRegistrosLiquido()
   {
	   return valorRegistrosLiquido;
   }
   
   public void setValorRegistrosLiquido(Moeda valorRegistrosLiquido)
   {
	   this.valorRegistrosLiquido = valorRegistrosLiquido;
   }

   public boolean isGerarArquivo()
   {
      return gerarArquivo;
   }

   public void setGerarArquivo(boolean gerarArquivo)
   {
      this.gerarArquivo = gerarArquivo;
   }

   public boolean isExibirListaLojas()
   {
      return exibirListaLojas;
   }

   public void setExibirListaLojas(boolean exibirListaLojas)
   {
      this.exibirListaLojas = exibirListaLojas;
   }
}
